﻿//-----------------------------------------------------------------------
// <copyright file="App.xaml.cs" company="Microsoft Corporation">
//     Copyright Microsoft Corporation. All Rights Reserved. This code released under the terms of the Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.) This is sample code only, do not use in production environments.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.ALMRangers.VsarTreasureMap.WindowsStoreApp
{
    using System;
    using System.Globalization;
    using System.Linq;
    using Microsoft.ALMRangers.VsarTreasureMap.WindowsStoreApp.LiveTile;
    using Microsoft.ALMRangers.VsarTreasureMap.WindowsStoreApp.Models;
    using Microsoft.ALMRangers.VsarTreasureMap.WindowsStoreApp.News;
    using Microsoft.ALMRangers.VsarTreasureMap.WindowsStoreApp.Views;
    using Windows.ApplicationModel.Activation;
    using Windows.System;
    using Windows.UI.ApplicationSettings;
    using Windows.UI.Notifications;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;

    /// <summary>
    /// Provides application-specific behaviour to supplement the default Application class.
    /// </summary>
    public sealed partial class App : Application
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="App" /> class.
        /// This is a singleton Application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            this.InitializeComponent();
            RangersNewsFeed = new RangersNewsFeed();
            Database = new DB();
            Database.LoadDBAsync().ContinueWith(t =>
                {
                    TileUpdater = TileUpdateManager.CreateTileUpdaterForApplication();
                    TileUpdater.EnableNotificationQueue(true);
                    TileGenerator.GeneratePercentageTile();

                    RangersNewsFeed.LoadItemsAsync().ContinueWith(_ =>
                        {
                            UpdateNewsTiles();
                        });
                }).Wait();
        }

        /// <summary>
        /// Gets the object representation of the application's dataset.
        /// </summary>
        /// <value>The database.</value>
        public static DB Database { get; private set; }

        /// <summary>
        /// Gets the rangers news feed.
        /// </summary>
        /// <value>The rangers news feed.</value>
        internal static RangersNewsFeed RangersNewsFeed { get; private set; }

        /// <summary>
        /// Gets the tile updater.
        /// </summary>
        /// <value>The tile updater.</value>
        internal static TileUpdater TileUpdater { get; private set; }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used when the application is launched to open a specific file, to display
        /// search results, and so forth.
        /// </summary>
        /// <param name="args">Details about the launch request and process.</param>
        protected override void OnLaunched(LaunchActivatedEventArgs args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            if (string.IsNullOrWhiteSpace(args.Arguments))
            {
                this.Launch(typeof(TreasureMapPage));
            }
            else
            {
                var tokenPosition = args.Arguments.IndexOf('-');
                var section = args.Arguments.Substring(0, tokenPosition);
                var id = Convert.ToInt32(args.Arguments.Substring(tokenPosition + 1), CultureInfo.InvariantCulture);

                switch (section)
                {
                    case "category":
                        {
                            this.Launch(typeof(Views.Category), id);
                            break;
                        }

                    case "project":
                        {
                            var project = (from c in Database.Categories
                                           from p in c.Projects
                                           where p.Id == id
                                           select p).Single();
                            var param = Tuple.Create(project.Category, project);
                            this.Launch(typeof(Views.Projects), param);
                            break;
                        }
                }
            }
        }

        /// <summary>
        /// This function is called when the search charm is activated
        /// </summary>
        /// <param name="args">Search Args Passed</param>
        protected override void OnSearchActivated(SearchActivatedEventArgs args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            if (Navigation.RootFrame != null)
            {
                var searchPage = Navigation.RootFrame.Content as Search;
                if (searchPage != null)
                {
                    var searchModel = searchPage.DataContext as ViewModels.Search;
                    searchModel.SearchContent(args.QueryText);
                    return;
                }
            }

            this.Launch(typeof(Search), args.QueryText);
        }

        /// <summary>
        /// Updates the news tiles.
        /// </summary>
        private static void UpdateNewsTiles()
        {
            var itemsForTile = RangersNewsFeed.Items.Take(3);
            foreach (var item in itemsForTile)
            {
                TileGenerator.GenerateNewsTile(item.Title, item.Content);
            }
        }

        /// <summary>
        /// Adds a command to the settings pane.
        /// </summary>
        /// <param name="sender">The settings pane.</param>
        /// <param name="args">The request.</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "launcher", Justification = "As we are working with async methods, we need to handle the response value but we do not care about the value itself.")]
        private void App_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
        {
            args.Request.ApplicationCommands.Add(
                new SettingsCommand(
                    "sendfeedback",
                    "Provide Feedback",
                    c =>
                    {
                        var launcher = Launcher.LaunchUriAsync(new Uri("mailto:vsartreasuremap@visualstudio.onmicrosoft.com?Subject=Feedback for the ALM Readiness Treasure Map Windows Store Application"));
                    }));

            args.Request.ApplicationCommands.Add(
                new SettingsCommand(
                    "privacyPref",
                    "Privacy Policy",
                    c =>
                    {
                        // Launch the privacy policy URL.
                        var launcher = Windows.System.Launcher.LaunchUriAsync(new Uri("http://aka.ms/vsartmapprivacy"));
                    }));
        }

        /// <summary>
        /// Deals with resize events
        /// </summary>
        /// <param name="sender">The parameter is not used.</param>
        /// <param name="e">The parameter is not used.</param>
        private void Current_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
        {
            Navigation.ReloadCurrentPage();
        }

        /// <summary>
        /// Attempts to launch the page of the specified type.
        /// </summary>
        /// <param name="page">Page attempting to Launch</param>
        /// <param name="parameter">boolean, true to add to back stack.</param>
        private void Launch(Type page, object parameter = null)
        {
            Frame rootFrame = Window.Current.Content as Frame;
            Navigation.RootFrame = rootFrame;

            if (rootFrame == null)
            {
                rootFrame = new Frame();
                rootFrame.KeyUp += this.RootFrameKeyUp;
                Window.Current.CoreWindow.PointerPressed += this.CoreWindow_PointerPressed;

                Window.Current.Content = rootFrame;
                Navigation.RootFrame = rootFrame;
            }

            if (rootFrame.Content == null || rootFrame.Content.GetType() != page)
            {
                Navigation.Navigate(page, parameter);
            }

            Window.Current.SizeChanged += this.Current_SizeChanged;
            Window.Current.Activate();

            SettingsPane.GetForCurrentView().CommandsRequested += this.App_CommandsRequested;
        }

        /// <summary>
        /// Cores the window_ pointer pressed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="Windows.UI.Core.PointerEventArgs"/> instance containing the event data.</param>
        private void CoreWindow_PointerPressed(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.PointerEventArgs args)
        {
            if (args.CurrentPoint.Properties.IsXButton1Pressed)
            {
                Navigation.GoBack();
            }
        }

        /// <summary>
        /// Handles the KeyUp event of the rootFrame control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="Windows.UI.Xaml.Input.KeyRoutedEventArgs"/> instance containing the event data.</param>
        private void RootFrameKeyUp(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e)
        {
            // How you should handle special keys: http://msdn.microsoft.com/en-us/library/windows/apps/hh700405.aspx
            // Supported keys (WinJS): http://msdn.microsoft.com/en-us/library/windows/apps/br211775.aspx
            // Supported keys (C#): http://msdn.microsoft.com/en-us/library/windows/apps/windows.system.virtualkey(v=win.10).aspx
            // Known bug cause problems with this and ALT+TAB, commented out in the hopes 8.1 fixes it and we can add it back.
            // http://social.msdn.microsoft.com/Forums/windowsapps/en-US/9bebfb0a-7637-400e-8bda-e55620091407/unexpected-behavior-in-windowscoreuicorephysicalkeystatusismenukeydown
            switch (e.Key)
            {
                case VirtualKey.Back:
                    {
                        Navigation.GoBack();
                        e.Handled = true;
                        break;
                    }
            }
        }     
    }
}
